package com.study.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import reactor.core.publisher.Mono;
import java.util.List;

/**
 * 事件推送 aware： 动态更新路由网关 service
 */
@Slf4j
@Service
@SuppressWarnings("all")//去除警告
public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware {

    //写路由定义
    private final RouteDefinitionWriter routeDefinitionWriter;

    //获取路由定义
    private final RouteDefinitionLocator routeDefinitionLocator;

    private ApplicationEventPublisher publisher;

    public DynamicRouteServiceImpl(RouteDefinitionWriter routeDefinitionWriter,
                                   RouteDefinitionLocator routeDefinitionLocator) {
        this.routeDefinitionWriter = routeDefinitionWriter;
        this.routeDefinitionLocator = routeDefinitionLocator;
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {

        //完成事件推送句柄的初始化
        this.publisher = applicationEventPublisher;
    }

    //增加路由定义
    public String addRouteDefinition(RouteDefinition definition) {

        log.info("gateway add route: [{}]", definition);

        //保存路由配置并发布
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();

        //发布事件通知给gateway 同步新增的路由定义
        this.publisher.publishEvent(new RefreshRoutesEvent(this));

        return "增加成功";
    }

    //更新路由
    public String updateList(List<RouteDefinition> definitions){

        log.info("更新路由：【{}】",definitions);

        //先拿到当前 gateway 中存储的路由定义
        List<RouteDefinition> routeDefinitionList = routeDefinitionLocator.getRouteDefinitions().buffer().blockFirst();

        if(!CollectionUtils.isEmpty(routeDefinitionList)){
            //删除之前"老的"路由定义
            routeDefinitionList.forEach(rd -> {
                log.info("删除路由定义： 【{}】",rd);
                deleteById(rd.getId());
            });
        }

        //把更新的路由定义 同步到gateway
        definitions.forEach(definition -> updateByRouteDefinition(definition));

        return "更新成功";
    }


    //根据路由id 删除路由配置
    private String deleteById(String id) {

        try {
            log.info("路由删除id: 【{}】",id);
            this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
            //发布事件通知给gateway 更新路由定义
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
            return "删除成功";
        } catch (Exception ex) {
            log.error("删除路由失败：【{}】", ex.getMessage(),ex);
            return "删除失败";
        }
    }

    //更新路由
    private String updateByRouteDefinition(RouteDefinition definition){

        try {
            log.info("更新路由：【{}】",definition);
            this.routeDefinitionWriter.delete(Mono.just(definition.getId()));

        }catch (Exception e){
            return "更新失败、没有找到路由id：【{}】" + definition.getId();
        }

        try {
            this.routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
            return "更新成功";
        }catch (Exception e){
            return "更新失败";
        }

    }
}
